#include "asm/memory.h"
#include "asm/asm-offsets.h"
#include "asm/thread_info.h"
#include "asm/assembler.h"
#include "linux/thread_info.h"

#include "entry-headers.S"

.global ret_from_fork
.global ret_fast_syscall

restore_user_regs:
	mov		r2, sp					@ r2 = 当前栈指针（指向pt_regs）
	ldr		r1, [r2, #S_PSR]		@ 从pt_regs加载保存的CPSR到r1
	ldr		lr, [r2, #S_PC]!	    @ 从pt_regs加载返回地址到lr，同时r2 = r2 + S_PC
	
	msr		spsr_cxsf, r1			@ 将保存的CPSR设置到SPSR
	ldmdb 	r2, {r0 - lr}^			@ 加载用户模式(system模式)下的寄存器，后面的^表示加载数据到用户模式下的寄存器中, 
									@ 所以这并不会覆盖第3步加到lr中的数据

	add 	sp, sp, #PT_REGS_SIZE	@ 恢复栈指针
	movs 	pc, lr					@ 返回到用户模式，将spsr复制到cpsr


ret_to_user:
ret_slow_syscall:
	b restore_user_regs


ret_fast_syscall:
	mov		r2, sp					@ r2 = 当前栈指针（指向pt_regs）
	ldr		r1, [r2, #S_PSR]		@ 从pt_regs加载保存的CPSR到r1
	ldr		lr, [r2, #S_PC]!	    @ 从pt_regs加载返回地址到lr，同时r2 = r2 + S_PC
	
	msr		spsr_cxsf, r1			@ 将保存的CPSR设置到SPSR
	ldmdb 	r2, {r1 - lr}^			@ 加载用户模式(system模式)下的寄存器，后面的^表示加载数据到用户模式下的寄存器中, 
									@ 所以这并不会覆盖第3步加到lr中的数据

	add 	sp, sp, #PT_REGS_SIZE	@ 恢复栈指针
	movs 	pc, lr					@ 返回到用户模式，将spsr复制到cpsr


ret_from_fork:
	cmp 	r5, #0
	movne 	r0, r4
	adrne 	lr, 1f
	movne 	pc, r5
1:	get_thread_info tsk
	b ret_slow_syscall